package org.mayanjun.code.easyweb.springmvc.interceptor;

import org.mayanjun.code.easyweb.springmvc.annotation.PrintAccessLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

/**
 * 打印请求的HTTP信息

 * @author mayanjun
 * @since 0.0.2(Jan 15, 2016)
 */
public class AccessLogInterceptor extends AnnotationBasedHandlerInterceptor {

	private static final Logger LOG = LoggerFactory.getLogger(AccessLogInterceptor.class);

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
			Object handler) throws Exception {

		PrintAccessLog pal = findAnnotation(PrintAccessLog.class, handler);
		if(pal != null) printLogInfo(request);
		return super.preHandle(request, response, handler);
	}

	private void printLogInfo(HttpServletRequest request) {
		AccessLog log = new AccessLog();

		log.setHeaders(formatHeaders(request));
		log.setParameters(formatParams(request));
		log.setMethod(request.getMethod());
		log.setProtocol(request.getProtocol());
		log.setUri(request.getRequestURI());
		log.setRemoteHost(request.getHeader("x-forwarded-for"));
		log.setSession(request.getSession().getId());

		String out = "\n+++++++++++++++ Access Log Interceptor +++++++++++++++"
				+ "\n-    Access Time: " + new Date() 
				+ "\n-   Request Line: " + log.getMethod() + " " + log.getProtocol() 
				+ "\n-    Request URI: " + log.getUri()
				+ "\n-    Remote Host: " + request.getRemoteAddr() + ":" + log.getRemoteHost()
				+ "\n-  Session isNew: " + request.getSession().isNew()
				+ "\n-     Session ID: " + log.getSession()
				// + "\n-   Action Class: " +
				// invocation.getAction().getClass().getName()
				// + "\n-    Action Name: " + proxy.getActionName()
				// + "\n-  Action Method: " + proxy.getMethod()
				// + "\n-   Execute Relt: " + proxy.getExecuteResult()
				+ "\n-Request Headers: " + log.getHeaders() + "\n- Request params: "
				+ log.getParameters()
				+ "\n-   Session Atts: " + formatSession(request)
				// + "\n-User Infomation: " +
				// formatUserInfo(request.getSession())
				+ "\n++++++++++++++ Access Log Interceptor END ++++++++++++\n";
		System.out.println(out);
	}

	private String formatHeaders(HttpServletRequest request) {
		StringBuilder sb = new StringBuilder();
		Enumeration<String> names = request.getHeaderNames();
		if (names != null) {
			while (names.hasMoreElements()) {
				String name = names.nextElement();
				sb.append("\n\t" + name).append(": ").append(request.getHeader(name));
			}
		}
		return sb.toString();
	}

	private String formatParams(HttpServletRequest request) {
		StringBuilder b = new StringBuilder();
		Map<String, String[]> pmap = request.getParameterMap();
		Iterator<Map.Entry<String, String[]>> it = pmap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, String[]> entry = it.next();
			b.append("\n\t" + entry.getKey()).append(": ");
			String[] vs = entry.getValue();
			if (vs == null)
				b.append("");
			else {
				if (vs.length == 0)
					b.append("");
				else if (vs.length == 1)
					b.append(vs[0]);
				else {
					b.append("[ ");
					for (String s : vs) {
						b.append(s).append(" | ");
					}
					int deliIndex = b.length() - 2;
					if (b.length() > 1 || b.charAt(deliIndex) == '|')
						b.deleteCharAt(deliIndex);
					b.deleteCharAt(b.length() - 1);
					b.append("]");
				}
			}
		}
		return b.toString();
	}

	private String formatSession(HttpServletRequest request) {
		StringBuilder sb = new StringBuilder();
		HttpSession session = request.getSession();
		if (session != null) {
			Enumeration<String> names = session.getAttributeNames();
			if (names != null) {
				while (names.hasMoreElements()) {
					String name = names.nextElement();
					sb.append("\n\t" + name).append(": ").append(session.getAttribute(name));
				}
			}
		}
		return sb.toString();
	}

	@Override
	public int getOrder() {
		return 0;
	}


	public class AccessLog {

		private static final long serialVersionUID = 926204865724469573L;

		private String headers;

		private String method;

		private String parameters;

		private String protocol;

		private String remoteHost;

		private String session;

		private String uri;

		public AccessLog() {
		}

		public String getHeaders() {
			return headers;
		}

		public void setHeaders(String headers) {
			this.headers = headers;
		}

		public String getMethod() {
			return method;
		}

		public void setMethod(String method) {
			this.method = method;
		}

		public String getParameters() {
			return parameters;
		}

		public void setParameters(String parameters) {
			this.parameters = parameters;
		}

		public String getProtocol() {
			return protocol;
		}

		public void setProtocol(String protocol) {
			this.protocol = protocol;
		}

		public String getRemoteHost() {
			return remoteHost;
		}

		public void setRemoteHost(String remoteHost) {
			this.remoteHost = remoteHost;
		}

		public String getSession() {
			return session;
		}

		public void setSession(String session) {
			this.session = session;
		}

		public String getUri() {
			return uri;
		}

		public void setUri(String uri) {
			this.uri = uri;
		}
	}
}
